package main;

import javax.swing.*;
import javax.swing.tree.*;
import mainSocket.Server;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.List;
import java.awt.*;
import storage.*;
import entity.*;
import java.awt.event.*;


public class ManagementFrame extends JFrame implements ActionListener 
{
	private JMenuBar bar = new JMenuBar();
	private JMenu menuStart = new JMenu("File");
	private JMenu menuEdit = new JMenu("Edit");
	private JMenu menuHelp = new JMenu("Help");
	private JMenuItem menuNew = new JMenuItem("New Database...");
	private JMenuItem menuStartQuit = new JMenuItem("Exit");	
	private JMenuItem menuHelpServerInfo = new JMenuItem("Server Info");
	private DataAccessManager data = new DataAccessManager();
	private UserAccessManager userData = new UserAccessManager();
	private int totalRows = 10;;  
	private int totalColumns = 10;
	private String[][] myObjs = new String[totalRows][totalColumns];
	private final JSplitPane pane = new JSplitPane();
	private final JScrollPane treePane = new JScrollPane();
	private DatabaseTree databaseTree = new DatabaseTree(this);
	private DefaultTreeModel databaseTreeModel;
	private final JToolBar treeToolBar = new JToolBar();
	private final JMenuItem mntmEditUserList = new JMenuItem("Edit user list");
	private final JPanel panel = new JPanel();
	private final JToolBar tabToolbar = new JToolBar();
	public final JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
	public List<Tab> tabs = new ArrayList<Tab>();
	public Server server;
	
	class MenuActionListener implements ActionListener
	{
        public void actionPerformed(ActionEvent e)
        {
                if (e.getSource() == menuNew)
                    getNew();
                if (e.getSource() == menuStartQuit)
                        System.exit(0);
                if (e.getSource() == menuHelpServerInfo)
                {
                	String ip="";
					try 
					{
						ip = InetAddress.getLocalHost().getHostAddress().toString();
					} 
					catch (UnknownHostException e1) 
					{
					}
                    JOptionPane.showMessageDialog(null,"IP : " + ip + "\n" + "Port : " + server.getPort(), "Server info", JOptionPane.INFORMATION_MESSAGE);    
                }
                if (e.getSource() == mntmEditUserList)
                {
                	openUserDialog();
                }
        }

		
	}	
	
	private void openUserDialog() 
	{
		EditUserDialog dialog = new EditUserDialog(this);
	}
	private void initMenu()
	{
		menuStart.add(menuNew);
		menuStart.add(menuStartQuit);
		menuHelp.add(menuHelpServerInfo);
		
		bar.add(menuStart);
		bar.add(menuEdit);
		
		menuEdit.add(mntmEditUserList);
		
		bar.add(menuHelp);
	}

	private void initListener()
	{
		MenuActionListener menuActionListener = new MenuActionListener();
		menuNew.addActionListener(menuActionListener);
		menuStartQuit.addActionListener(menuActionListener);
		menuHelpServerInfo.addActionListener(menuActionListener);
		mntmEditUserList.addActionListener(menuActionListener);
	}
	
	void buildConstraints(GridBagConstraints gbc,int gx, int gy, int gw, int gh, int wx, int wy)
	{
		gbc.gridx = gx;			
		gbc.gridy = gy;			
		gbc.gridwidth = gw;		
		gbc.gridheight = gh;	
		gbc.weightx = wx;		
		gbc.weighty = wy;		
	}
	
	private void setMyPane()
	{
		initMenu();	
		setJMenuBar(bar);

		databaseTree.setShowsRootHandles(true);
		databaseTree.putClientProperty("JTree.lineStyle", "None");
		databaseTree.setToggleClickCount(0);
		databaseTree.setCellRenderer(new TreeRenderer(new ImageIcon("icons/Database.png", ""),
														new ImageIcon("icons/Table.png", ""),
														new ImageIcon("icons/Column.png", "")));
		
		getContentPane().setLayout(null);
		getContentPane().setLayout(new BorderLayout(0, 0));
		getContentPane().setLayout(new BorderLayout(0, 0));
		pane.setResizeWeight(0.11);
		
		getContentPane().add(pane, BorderLayout.CENTER);
		treePane.setBounds(10, 5, 160, 708);
		pane.setLeftComponent(treePane);

		treePane.setViewportView(databaseTree);
		treePane.setColumnHeaderView(treeToolBar);
		treeToolBar.setFloatable(false);
		treeToolBar.add(makeNavigationButton("Database-Refresh", "refreshDatabase", "Refresh the database", "Refresh the database"));
		treeToolBar.add(makeNavigationButton("Database-Add", "addDatabase", "Add a database", "Add a database"));
		treeToolBar.add(makeNavigationButton("Database-Delete", "deleteDatabase", "Delete the database", "Delete the database"));
		treeToolBar.add(makeNavigationButton("Table-Add", "addTable", "Add a table", "Add a table"));
		treeToolBar.add(makeNavigationButton("Table-Delete", "deleteTable", "Delete the table", "Delete the table"));
		
		pane.setRightComponent(panel);
		panel.setLayout(new BorderLayout(0, 0));
		
		panel.add(tabToolbar, BorderLayout.NORTH);
		
		tabToolbar.setFloatable(false);
		tabToolbar.add(makeNavigationButton("Row-Add", "addRow", "Add a row", "Add a row"));	
		tabToolbar.add(makeNavigationButton("Row-Delete", "deleteRow", "Delete the row", "Delete the row"));
		tabToolbar.add(makeNavigationButton("Save", "saveTable", "Save the table", "Save the table"));	
		tabToolbar.add(Box.createHorizontalGlue());
		tabToolbar.add(makeNavigationButton("Close", "closeTab", "Close the tab", "Close the tab"));	

		panel.add(tabbedPane, BorderLayout.CENTER);

	}
	
	public JButton makeNavigationButton(String imageName,String actionCommand,String toolTipText, String altText) 
	{
		String imgLocation = "icons/" + imageName + ".png";
		
		JButton button = new JButton();
		button.setActionCommand(actionCommand);
		button.setToolTipText(toolTipText);
		button.addActionListener(this);
		button.setIcon(new ImageIcon(imgLocation, altText));
		button.setBorderPainted(false);
		button.setFocusable(false);
		return button;
	}
	
	public void addDataTab(String databaseName,String tableName)
	{
		data.refreshList();
		Tab tab = new Tab(this,new JScrollPane(),new JTable(),data.getDatabaseByName(databaseName).getTableByName(tableName),data.getDatabaseByName(databaseName));
		tab.refreshTable();
		tabs.add(tab);
		tabbedPane.addTab("Edit " + tableName, null, tab.getPane(), null);
	}
	
	private void getNew()
	{
		CreateDatabaseDialog cdb = new CreateDatabaseDialog(this);
	}
	
	
	private void createTreeNodes(DefaultMutableTreeNode top) 
	{
		data.refreshList();
		List<Database> databaseList = data.getDatabaseList();
		for (int i=0;i<databaseList.size();i++)
		{
			Database database = databaseList.get(i);
			DefaultMutableTreeNode databaseNode = new DefaultMutableTreeNode(database.getName());
			for (int j=0;j<database.getTablesCount();j++)
			{
				Table table = database.getTableAt(j);
				DefaultMutableTreeNode tableNode = new DefaultMutableTreeNode(table.getName());
				for (int k=0;k<table.getColumnsCount();k++)
				{
					Column column = table.getColumnAt(k);
					DefaultMutableTreeNode columnNode = new DefaultMutableTreeNode(column.getName());
					tableNode.add(columnNode);
				}
				databaseNode.add(tableNode);
			}
			top.add(databaseNode);
		}
	}
	
	public void refreshDatabaseTree()
	{
		DefaultMutableTreeNode top = new DefaultMutableTreeNode("Databases");
		createTreeNodes(top);
		databaseTreeModel = new DefaultTreeModel(top);
		databaseTree.setVisibleRowCount(1000);
		databaseTree.setModel(databaseTreeModel);
		
	}
	public ManagementFrame()
	{
		setTitle("Database Server");
		setSize(760,536);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setMyPane();
		initListener();
		setVisible(true);
		refreshDatabaseTree();
		try 
		{
			server = new Server();
			server.run();
		} 
		catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, "Error creating server socket.");
			this.dispose();
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) 
	{
		TreePath path = databaseTree.getSelectionPath();
		if (e.getActionCommand().equals("refreshDatabase")) refreshDatabaseTree();
		if (e.getActionCommand().equals("addDatabase")) databaseTree.newDatabase();
		if (e.getActionCommand().equals("deleteDatabase")) if (path!=null) if (path.getPathCount()>=2) databaseTree.deleteDatabase();
		if (e.getActionCommand().equals("addTable")) if (path!=null) if (path.getPathCount()>=2) databaseTree.newTable();
		if (e.getActionCommand().equals("deleteTable")) if (path!=null) if (path.getPathCount()>=2) databaseTree.deleteTable();
		if (e.getActionCommand().equals("addRow") && tabbedPane.getSelectedIndex()!=-1) 
		{
			tabs.get(tabbedPane.getSelectedIndex()).getModel().addRow(new String[tabs.get(tabbedPane.getSelectedIndex()).getTable().getRowCount()]);
		}
		if (e.getActionCommand().equals("deleteRow") && tabbedPane.getSelectedIndex()!=-1 && tabs.get(tabbedPane.getSelectedIndex()).getJTable().getSelectedRow()!=-1) 
		{
			tabs.get(tabbedPane.getSelectedIndex()).getModel().removeRow(tabs.get(tabbedPane.getSelectedIndex()).getJTable().getSelectedRow());
		}
		if (e.getActionCommand().equals("saveTable") && tabbedPane.getSelectedIndex()!=-1) 
		{
			if (tabs.get(tabbedPane.getSelectedIndex()).Save()==0)
			{
				Database database = tabs.get(tabbedPane.getSelectedIndex()).getDatabase();
				Table table = tabs.get(tabbedPane.getSelectedIndex()).getTable();
				data.getDatabaseByName(database.getName()).updateTable(data.getDatabaseByName(database.getName()).getTableByName(table.getName()), table);
				data.saveDatabases();
				tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), "Edit "+tabs.get(tabbedPane.getSelectedIndex()).getTable().getName());
			}
		}
		if (e.getActionCommand().equals("closeTab") && tabbedPane.getSelectedIndex()!=-1) 
		{
			if (!tabs.get(tabbedPane.getSelectedIndex()).IsSaved()) 
			{
				int result = JOptionPane.showConfirmDialog(this, "The table has been modified. Save changes?");
				if (result==JOptionPane.YES_OPTION)
				{
					if (tabs.get(tabbedPane.getSelectedIndex()).Save()==0) 
					{
						Database database = tabs.get(tabbedPane.getSelectedIndex()).getDatabase();
						Table table = tabs.get(tabbedPane.getSelectedIndex()).getTable();
						data.getDatabaseByName(database.getName()).updateTable(data.getDatabaseByName(database.getName()).getTableByName(table.getName()), table);
						data.saveDatabases();data.saveDatabases();
					}
					else return;
				}
				else if (result==JOptionPane.CANCEL_OPTION) return;
			}
			tabs.remove(tabbedPane.getSelectedIndex());
			tabbedPane.remove(tabbedPane.getSelectedIndex());
		}
		
	}
}
